import re
import requests

from time import time
from datetime import datetime

from core.models import Link, Scan
from core.models import Provider
from core.models import Variable
from core.models import ProxyServer

from app.utils import Elements
from app.utils import informator
from app.utils import Worker
from app.utils import ThreadWorker

from app.config import MAX_THREADS

THREAD_ALLOWED = True

def get_proxy():
    try:
        return ProxyServer.objects.get(use = True)
    except ProxyServer.DoesNotExist:
        return None

def get_provider():
    ip_pattern = r'[0-9]+(?:\.[0-9]+){3}'
    ip_service = object

    try:
        ip_service = Variable.objects.get(key = 'ip_service').value
    except Variable.DoesNotExist:
        return None

    response = requests.get(ip_service)
    ip_address = re.findall(ip_pattern, response.content)

    if not ip_address or len(ip_address) is 0:
        return None

    for provider in Provider.objects.all():
        p_one = str(provider.ip_range.split('.')[0])
        p_two = str(provider.ip_range.split('.')[1])

        for ip in ip_address:
            ip_one = str(ip.split('.')[0])
            ip_two = str(ip.split('.')[1])

            if p_one == ip_one and p_two == ip_two:
                return provider

    return None

def distribute(use_multiprocess = THREAD_ALLOWED):
    links = Link.objects.all()
    threads = 2

    if not len(links):
        return None

    if len(links) > MAX_THREADS:
        threads = MAX_THREADS

    if use_multiprocess:
        return Elements().split_equal(num_threads = threads, array = links)
    else:
        return links

def run(meta = object):
    thread_list = []
    provider = meta['provider']
    links_count = Link.objects.all().count()

    meta['proxy']['use'] = meta['use_proxy']

    current_scan = Scan()
    current_scan.priority = -1
    current_scan.num_links = links_count
    current_scan.provider = provider
    current_scan.save()

    time_started = datetime.fromtimestamp(meta['time_started'])

    print time_started.strftime('%Y-%m-%d %H:%M:%S')

    current_scan.title = 'Scan: %s' % time_started.strftime('%Y-%m-%d %H:%M:%S')
    current_scan.start_date = time_started.strftime('%Y-%m-%d %H:%M:%S')
    current_scan.num_links = links_count

    # TODO: Schedule need to associated when will be ready
    current_worker = Worker(proxy_info = meta['proxy'], provider = provider)

    if not meta['use_threads']:
        for link in meta['links']:
            transfer = []
            transfer.append(link)
            current_worker.start(links = transfer, scan = current_scan)
    else:
        for links in meta['links']:
            #print i
            thread = ThreadWorker(worker=current_worker, 
                                  scan=current_scan, 
                                  links=links,
                                  schedule=None)

            thread_list.append(thread)

        for thread in thread_list:
            thread.start()

        for thread in thread_list:
            thread.join()

    end = datetime.fromtimestamp(time())

    current_scan.priority = 1
    current_scan.end_date = end.strftime('%Y-%m-%d %H:%M:%S')

    current_scan.save()

    informator('End time %s' % end.strftime('%Y-%m-%d %H:%M:%S'))
